package MuleBackend;

import java.util.ArrayList;
import java.util.Random;

/**
 * holds all the lands and represents the Map on which MULE takes place
 * 
 * @author Andrew
 * 
 */
public class Board {
	Land[][] lands;
	// nextFreeLand is used to hold the freeLand from the land Sale phase so
	// that it can be used in the Land Auction phase
	Land nextFreeLand;

	/**
	 * constructor for the board holds a 2d array of all the lands
	 */
	public Board() {
		lands = new Land[5][9];
	}

	/**
	 * @return the string representation of the board
	 */
	public String toString() {
		String string = "";
		for (int i = 0; i < lands.length; i++) {
			for (int j = 0; j < lands[i].length; j++) {
				System.out.println(lands[i][j].toString());
			}
		}
		return string;
	}

	/**
	 * finds a random land to be the focal point of a crystite deposit before creating the map.
	 * Will not select the same land twice.
	 * @param num
	 */
	public void createMap(int num){
		int[] r={-1,-1,-1};
		int[] c={-1,-1,-1};
		for (int points = 0; points < 3; points++) {
			randomize:
			while(true){
				r[points] = (int) (Math.random() * lands.length);
				c[points] = (int) (Math.random() * lands[0].length);
				for(int i=0;i<3;i++){
					if(i==points)continue;
					if((r[points]==r[i]&&c[points]==c[i])||(r[points]==3&&c[points]==5))
						continue randomize;
				}
				break;
			}
		}
		createMap(num,r,c);
	}
	
	/**
	 * generates the board based on the map selected
	 * 
	 * @param num
	 *            the map selected
	 */
	public void createMap(int num, int[]r,int[]c) {
		String layout = mapPattern(num);
		int index = 0;
		for (int i = 0; i < lands.length; i++) {
			for (int j = 0; j < lands[i].length; j++) {
				lands[i][j] = new Land(layout.charAt(index) - 48);
				lands[i][j].setLocation(i, j);
				index++;
			}
		}

		//set the crystite deposits
		for (int points = 0; points < 3; points++) {
			
			// set the lows
			for (int i = 0; i < 3; i++) {
				for (int j = 0; j < 3; j++) {
					if(r[points] + i - j==2&&c[points] + i + j-2==4)continue;
					try {
						lands[r[points] + i - j][c[points] + i + j-2].raiseCrystiteTo(1);	
						System.out.println("land["+ (r[points] + i - j)+"]["+ (c[points] + i + j-2)+"] set to low.");
					} catch (ArrayIndexOutOfBoundsException e) {
					}
				}
			}
			// set the mediums
			for (int i = 0; i < 2; i++) {
				for (int j = 0; j < 2; j++) {
					if(r[points] + i - j==2&&c[points] + i + j-1==4)continue;
					try {
						lands[r[points] + i - j][c[points] + i + j-1].raiseCrystiteTo(2);
						System.out.println("land["+ (r[points] + i - j)+"]["+ (c[points] + i + j-1)+"] set to medium.");
					} catch (ArrayIndexOutOfBoundsException e) {
					}
				}
			}
			// set the high
			if(r[points]!=2||c[points]!=4)
				lands[r[points]][c[points]].raiseCrystiteTo(3);
			System.out.println("land["+r[points]+"]["+c[points]+"] set to high");
		}
	}

	// 0 = Town
	// 1 = Mountain1
	// 2 = Mountain2
	// 3 = Mountain3
	// 4 = Plains
	// 5 = River
	/**
	 * private method that holds the map structure (the layout of the lands and
	 * their types)
	 * 
	 * @param num
	 *            the map number
	 * @return
	 */
	private String mapPattern(int num) {
		if (num == 1) {
			return "441454344" + // row 1
					"414454443" + // row 2
					"344404441" + // row 3
					"424454244" + // row 4
					"442454442"; // row 5
		} else {
			return randomize();
		}

	}
	
	private String randomize() {
		Random randy = new Random();
		String randomMap = "";
		for (int j = 0; j < 5; j++) {
			for (int i = 0; i < 4; i ++) {
				randomMap += (randy.nextInt(4) + 1);
			}
			if (j == 2) {
				randomMap += 0;
			} else {
				randomMap += 5;
			}
			for (int i = 0; i < 4; i ++) {
				randomMap += (randy.nextInt(4) + 1);
			}
		}
		
		return randomMap;
	}

	/**
	 * 
	 * @return the 2d array of lands the board contains
	 */
	public Land[][] getLandsArray() {
		return lands;
	}

	/**
	 * creates a list of free lands
	 * 
	 * @return list of free lands
	 */
	public ArrayList<Land> getFreeLands() {
		ArrayList<Land> freeLands = new ArrayList<Land>();
		for (int r = 0; r < 5; r++)
			for (int c = 0; c < 9; c++)
				if (c == 4)
					continue;
				else if (lands[r][c].getOwner() == null)
					freeLands.add(lands[r][c]);
		return freeLands;
	}

	/**
	 * find function
	 * 
	 * @param land
	 *            land to be searched for
	 * @return index in lands where it's located, -1 if it doesn't exist in
	 *         lands. The index is calculated as 9*row + col
	 */
	public int findLandIndex(Land land) {
		for (int r = 0; r < 5; r++)
			for (int c = 0; c < 9; c++)
				if (land == lands[r][c])
					return r * 9 + c;
		return -1;
	}

	/**
	 * Sets the freeLand
	 */
	public void setNextFreeLand(Land freeLand) {
		nextFreeLand = freeLand;
	}

	/**
	 * gets the free land
	 * 
	 * @return free land
	 */
	public Land getNextFreeLand() {
		return nextFreeLand;
	}
}
